package middleware

import (
	"fmt"
	"time"

	"net/http"

	jwt "github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
)

type Claims struct {
	Uid      string `json:"uid"`
	Username string `json:"username"`
	Mobile   string `json:"mobile"`
	jwt.StandardClaims
}

var (
	secret = []byte("itScrNjsZfEaN+aEjn9DtIWh17XskW0EGEmvUseW$$YN$X8rAlBuomEHCjS0$iwJlwgj0Z9AJ6z5UToEv4kMad7BZ_y$D@YqjhNYQJ_jAxuHA$A3G3oBKS9kfXAWbQxBX2VlD_4QUR@dS$lLB1y9+CnwIu21n")

	//该路由下不校验token
	noVerify = []interface{}{"/login", "/ping"}

	//token有效时间（纳秒）
	effectTime = 24 * 365 * time.Hour
)

func GetToken(data map[string]string) string {

	claims := &Claims{
		Uid:      data["uid"],
		Username: data["username"],
		Mobile:   data["mobile"],
	}
	return GenerateToken(claims)
}

// 生成token
func GenerateToken(claims *Claims) string {

	claims.ExpiresAt = time.Now().Add(effectTime).Unix()

	//生成token
	sign, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(secret)

	if err != nil {

		panic(err)
	}
	return sign
}

func parseToken(token string) (*Claims, error) {

	tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return secret, nil
	})
	if tokenClaims != nil {
		if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid { // Valid()验证基于时间的声明
			return claims, nil
		}
	}
	return nil, err
}

func ApiAuth(c *gin.Context) {

	token := c.Request.Header.Get("Token")
	_, err := parseToken(token)

	if err != nil {
		c.Abort()
		c.JSON(http.StatusUnauthorized, gin.H{
			"Code": http.StatusUnauthorized,
			"Msg":  "无法认证，重新登录",
			"Data": nil,
		})
	}
	c.Next()
}

func TokenEncode(uid string, data map[string]string) (string, bool) {
	if uid == "" {
		return "", false
	}
	kv := getKv("")
	strKey := []byte(kv["k"])
	c := Claims{
		Username: data["username"],
		Mobile:   data["phone"],
		Uid:      uid,
		StandardClaims: jwt.StandardClaims{
			NotBefore: time.Now().Unix() - 1,
			ExpiresAt: time.Now().Unix() + 60*60*24,
			Issuer:    kv["kv"],
		},
	}
	fmt.Println("--------------------------------------------------------------------------------------------------------")
	fmt.Println(c)
	fmt.Println("--------------------------------------------------------------------------------------------------------")
	t := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
	s, _ := t.SignedString(strKey)
	return s, true
}

// 获取K-V
func getKv(str ...string) map[string]string {
	kv := make(map[string]string)
	kv["k"] = "itScrNjsZfEaN+aEjn9DtIWh17XskW0EGEmvUseW$$YN$X8rAlBuomEHCjS0$iwJlwgj0Z9AJ6z5UToEv4kMad7BZ_y$D@YqjhNYQJ_jAxuHA$A3G3oBKS9kfXAWbQxBX2VlD_4QUR@dS$lLB1y9+CnwIu21n"
	kv["issuer"] = "jslog"
	return kv
}

func GetInfo(c *gin.Context) (*Claims, error) {

	reTokan, err := parseToken(c.Request.Header.Get("Token"))
	if err == nil {
		return reTokan, nil
	}
	return nil, err
}

// 解析Token
func ParseT(token string) (*Claims, error) {

	tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {

		return secret, nil
	})
	fmt.Println("------------------------------------------")
	fmt.Println(tokenClaims)
	fmt.Println("------------------------------------------")
	if tokenClaims != nil {
		if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid { // Valid()验证基于时间的声明
			return claims, nil
		}
	}
	return nil, err
}
